VERSION = 0
PATCHLEVEL = 96
SUBLEVEL = 0
EXTRAVERSION = .0
NAME = photon-rtos

#不要再屏幕上打印"Entering directory.."
MAKEFLAGS += -rR --no-print-directory

#如果命令行指定了“V”参数，表示需要输出详细信息
ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

# 源代码检查
#
# 使用'make C=1'，仅仅检查重新编译的文件。
# 使用'make C=2'，将对'所有'源文件进行检查，而不管是否重新编译它。
ifeq ("$(origin C)", "command line")
  KBUILD_CHECKSRC = $(C)
endif
ifndef KBUILD_CHECKSRC
  KBUILD_CHECKSRC = 0
endif

srctree		:= $(CURDIR)
objtree		:= $(CURDIR)
export srctree objtree

# 如果没有指定编译目标，那么默认就是_all
PHONY := all

# 交叉编译使用不同的gcc/bin-utils集合
# ---------------------------------------------------------------------------
#
# 当执行交叉编译时，应当指定ARCH参数为目标体系结构。
# ARCH可以象如下命令一样指定：
# make ARCH=ia64
# 另一种方式是指定ARCH环境变量。默认ARCH是make执行时的主机体系结构。

# CROSS_COMPILE指定了交叉编译时的前缀。仅仅只有gcc和相关的bin-utils执行时，
# 才使用$(CROSS_COMPILE)作为前缀。
# CROSS_COMPILE可以在命令行指定，如：
# make CROSS_COMPILE=ia64-photon-
# 可选的，可以在环境变量中指定CROSS_COMPILE。
# 第三种方法是在.config中保存交叉编译的设置。
export KBUILD_BUILDHOST := $(shell uname -m)
ARCH		?= arm
CROSS_COMPILE	?= $(CONFIG_CROSS_COMPILE:"%"=%)

# 写入到compile.h
SRCARCH 	:= $(ARCH)

KCONFIG_CONFIG	?= .config
export KCONFIG_CONFIG

# 使用的shell
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
	  else if [ -x /bin/bash ]; then echo /bin/bash; \
	  else echo sh; fi ; fi)

#
# 主机上的编译工具
#
HOSTCC       = gcc
HOSTCXX      = g++
HOSTCFLAGS   = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
HOSTCXXFLAGS = -O2

#
# 是否编译模块.
#
KBUILD_MODULES :=
KBUILD_BUILTIN := 1

export  KBUILD_BUILTIN KBUILD_MODULES
export KBUILD_CHECKSRC

# 修饰输出格式
# ---------------------------------------------------------------------------
#
# 一般情况下，在执行命令前，我们回显完整的命令
# 可以设置$(quiet)来选择其他的输出格式。
#
#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
#
# 如果$(quiet)为空，整个命令会被打印出来
# 如果设置为"quiet_", 仅仅打印短版本
# 如果设置为"silent_", 什么都不会被打印，因为$(silent_cmd_cc_o_c)根本不存在。
#
# 在non-verbose模式下，在命令前面的简单变量$(Q)，将隐藏执行的命令
#
#	$(Q)ln $@ :<
#
# 如果KBUILD_VERBOSE等于0，上面的命令将被隐藏
# 如果KBUILD_VERBOSE等于1，那么上面的命令将被显示出来
ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif

# 如果用户运行make -s，则不回显命令
ifneq ($(findstring s,$(MAKEFLAGS)),)
  quiet=silent_
endif

export quiet Q KBUILD_VERBOSE

# 将源代码根目录添加到include路径。
MAKEFLAGS += ---dir=$(srctree)

# 一些通常的定义
$(srctree)/scripts/Kbuild.include: ;
include $(srctree)/scripts/Kbuild.include

# Make变量，如CC...
AS		= $(CROSS_COMPILE)as
LD		= $(CROSS_COMPILE)ld
CC		= $(CROSS_COMPILE)gcc
CPP		= $(CC) -E
AR		= $(CROSS_COMPILE)ar
NM		= $(CROSS_COMPILE)nm
STRIP		= $(CROSS_COMPILE)strip
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdump
AWK		= awk
GENKSYMS	= scripts/genksyms/genksyms
KALLSYMS	= scripts/kallsyms
PERL		= perl
CHECK		= sparse

CHECKFLAGS     := -D__photon__ -Dphoton -D__STDC__ \
		  -Wbitwise -Wno-return-void $(CF)
CFLAGS_KERNEL	=
AFLAGS_KERNEL	=

#
# 包含文件路径
#
USERINCLUDE    := \
		-I$(srctree)/arch/$(ARCH)/include/uapi \
		-Iarch/$(ARCH)/include/generated/uapi \
		-I$(srctree)/arch/$(ARCH)/include/uapi \
		-I$(srctree)/include/uapi \
		-Iinclude/generated/uapi \

KLIBCINCLUDE	:=	\
		-include include/generated/autoconf.h \
		-I$(srctree)/arch/$(ARCH)/include/uapi \
		-Iarch/$(ARCH)/include/generated/uapi \
		-I$(srctree)/arch/$(ARCH)/include/uapi


PHOTONINCLUDE    := -I$(srctree)/arch/$(ARCH)/include -Iinclude \
                   $(if $(KBUILD_SRC), -I$(srctree)/include) \
				   -Iarch/$(ARCH)/include/generated \
				   -Iarch/$(ARCH)/include/generated/uapi \
				   -include include/generated/autoconf.h	\
				   -Iarch/$(ARCH)/include/generated/ \
				   -Iinclude/asm-generic/ \
				   -Iinclude/generated/ \
				   -Iusr/include/asm-generic/ \
				   -Iinclude \
				   $(USERINCLUDE)

KBUILD_CPPFLAGS := -D__KERNEL__

KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -Wno-unused-function \
		   -fno-strict-aliasing -fno-common \
		   -Wno-format-security \
		   -Wno-main \
		   -fno-delete-null-pointer-checks \
		   -fno-tree-scev-cprop -Wmissing-declarations -Wmissing-prototypes
KBUILD_AFLAGS_KERNEL :=
KBUILD_CFLAGS_KERNEL := -fno-tree-scev-cprop
KBUILD_AFLAGS   := -D__ASSEMBLY__
KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds

#
# 从include/config/kernel.release中读取值到KERNELRELEASE变量中
#
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)

export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP
export MAKE AWK GENKSYMS PERL
export HOSTCXX HOSTCXXFLAGS CHECK CHECKFLAGS

export KBUILD_CPPFLAGS NOSTDINC_FLAGS KLIBCINCLUDE PHOTONINCLUDE OBJCOPYFLAGS LDFLAGS
export KBUILD_CFLAGS CFLAGS_KERNEL
export KBUILD_AFLAGS AFLAGS_KERNEL
export    KBUILD_LDFLAGS_MODULE
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL

#
# 在查找时，忽略这些文件
# 这些文件不会被清除，也不会参与编译
#
RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o
export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git

# ===========================================================================
# 用于*config配置文件的规则

# scripts/目录下的辅助目标
PHONY += scripts_basic
scripts_basic:
	make -f scripts/Makefile.build obj=scripts/basic
	$(Q)$(MAKE) $(build)=scripts/basic
	$(Q)rm -f .tmp_quiet_recordmcount

#
# 隐含的空命令
#
scripts/basic/%: scripts_basic ;

# 在这些目标中，不能包含.config
no-dot-config-targets := clean mrproper distclean \
			 cscope TAGS tags    %docs check% coccicheck \
			 headers_% \
			 kernelversion %src-pkg

config-targets := 0
mixed-targets  := 0
dot-config     := 1

ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
	ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
		dot-config := 0
	endif
endif

ifneq ($(filter config %config,$(MAKECMDGOALS)),)
        config-targets := 1
        ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
                mixed-targets := 1
        endif
endif

ifeq ($(mixed-targets),1)
# ===========================================================================
# We're called with mixed targets (*config and build targets).
# Handle them one by one.

%:: FORCE
	$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@

else
ifeq ($(config-targets),1)
# ===========================================================================
# 仅仅是构建*config目标

# 读取体系特定的Makefile以设置KBUILD_DEFCONFIG
# 使用defconfig可以为KBUILD_DEFCONFIG指定默认的配置
include $(srctree)/arch/$(ARCH)/Makefile
export KBUILD_DEFCONFIG KBUILD_KCONFIG

config: scripts_basic FORCE
	$(Q)mkdir -p include/config
	$(Q)$(MAKE) $(build)=scripts/kconfig $@
#@mkdir -p include/chsuhi include/config
#@make -f scripts/Makefile.build obj=scripts/kconfig menuconfig
%config: scripts_basic FORCE
	$(Q)mkdir -p include/config
	$(Q)$(MAKE) $(build)=scripts/kconfig $@

else
# ===========================================================================
# 仅仅构建目标-包含photon, 体系特定目标, clean及其他

PHONY += scripts
scripts: scripts_basic include/config/auto.conf include/config/tristate.conf
	$(Q)$(MAKE) $(build)=$(@)

# 链接到photon中的子目录
init-y		:= init/
libs-y		:= lib/
core-y		:= kernel/
apps-y		:= apps/

# 构建目标需要引用配置文件
ifeq ($(dot-config),1)
# Read in config
-include include/config/auto.conf

# 配置文件
-include include/config/auto.conf.cmd

$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;

#
# .config文件比auto.conf新，执行silentoldconfig生成auto.conf
#
include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig

else
include/config/auto.conf: ;
endif # $(dot-config)

# 默认的构建目标，在体系特定的Makefile中，一般还会添加其他目标到all中
all: photon

KBUILD_CFLAGS	+= -DCONFIG_OSEK=y

#
# CONFIG_CC_OPTIMIZE_FOR_SIZE在auto.conf中被添加进来了
#
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS	+= -O0
else
KBUILD_CFLAGS	+= -O0
endif

# 添加体系结构特定的Makefile
include $(srctree)/arch/$(ARCH)/Makefile

#
# 用户配置了栈帧告警
# 调整编译参数
#
ifneq ($(CONFIG_FRAME_WARN),0)
KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
endif

#
# 用户配置了堆栈保护
# 调整编译参数
#
ifndef CONFIG_CC_STACKPROTECTOR
KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
endif

#
# 用户配置了栈帧参数
# 调整编译参数，确保生成栈帧，简化堆栈打印
#
ifdef CONFIG_FRAME_POINTER
KBUILD_CFLAGS	+= -fno-omit-frame-pointer -fno-optimize-sibling-calls
else
KBUILD_CFLAGS	+= -fomit-frame-pointer
endif

ifdef CONFIG_IOC
KBUILD_CFLAGS	+= -Iapps/UnitTest
endif

# arch Makefile may override CC so keep this after arch Makefile is included
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS     += $(NOSTDINC_FLAGS)

# warn about C99 declaration after statement
KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)

# disable pointer signed / unsigned warnings in gcc 4.0
KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,)

# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS	+= $(call cc-option,-fno-strict-overflow)

# conserve stack if available
KBUILD_CFLAGS   += $(call cc-option,-fconserve-stack)

# 将用户定义的CPPFLAGS，AFLAGS，CFLAGS添加到编译选项中
# 但是在添加前向用户提示警告信息
warn-assign = \
$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)")

ifneq ($(KCPPFLAGS),)
        $(call warn-assign,CPPFLAGS)
        KBUILD_CPPFLAGS += $(KCPPFLAGS)
endif
ifneq ($(KAFLAGS),)
        $(call warn-assign,AFLAGS)
        KBUILD_AFLAGS += $(KAFLAGS)
endif
ifneq ($(KCFLAGS),)
        $(call warn-assign,CFLAGS)
        KBUILD_CFLAGS += $(KCFLAGS)
endif

# Use --build-id when available.
LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
			      $(call cc-ldoption, -Wl$(comma)--build-id,))
KBUILD_LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID)
LDFLAGS_photon += $(LDFLAGS_BUILD_ID)

ifeq ($(CONFIG_STRIP_ASM_SYMS),y)
LDFLAGS_photon	+= $(call ld-option, -X,)
endif

# 如果没有指定内核映像名称，就使用默认的photon
# KBUILD_IMAGE可以被命令行或者环境变量覆盖
# 也可以在arch/$(ARCH)/Makefile中设置此值
export KBUILD_IMAGE ?= photon

#
# INSTALL_PATH指定放置内核和map文件的默认位置
# 默认值是/boot
export	INSTALL_PATH ?= /boot

#
# INSTALL_MOD_PATH指定MODLIB的前缀。
# 在Makefile中没有指定其值，但是可以指定环境变量。
#

MODLIB	= $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB

#
# 去除模块中的符号

ifdef INSTALL_MOD_STRIP
ifeq ($(INSTALL_MOD_STRIP),1)
mod_strip_cmd = $(STRIP) --strip-debug
else
mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
endif # INSTALL_MOD_STRIP=1
else
mod_strip_cmd = true
endif # INSTALL_MOD_STRIP
export mod_strip_cmd

# 要编译的核心目录文件
core-y         += autosar/

# photon需要编译的目录
photon-dirs	:= $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
		     $(core-y) $(core-m) \
		     $(libs-y) $(libs-m) \
		     $(apps-y) $(apps-m)))

photon-alldirs	:= $(sort $(photon-dirs) $(patsubst %/,%,$(filter %/, \
		     $(init-n) $(init-) \
		     $(core-n) $(core-) \
		     $(libs-n) $(libs-) $(apps-n) $(apps-))))

init-y		:= $(patsubst %/, %/built-in.o, $(init-y))
core-y		:= $(patsubst %/, %/built-in.o, $(core-y))
libs-y1		:= $(patsubst %/, %/lib.a, $(libs-y))
libs-y2		:= $(patsubst %/, %/built-in.o, $(libs-y))
libs-y		:= $(libs-y1) $(libs-y2)
apps-y	:= $(patsubst %/, %/built-in.o, $(apps-y))

# 构建photon
# ---------------------------------------------------------------------------
# photon is built from the objects selected by $(photon-init) and
# $(photon-main). Most are built-in.o files from top-level directories
# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
# Ordering when linking is important, and $(photon-init) must be first.
#
# photon
#   ^
#   |
#   +-< $(photon-init)
#   |   +--< init/version.o + more
#   |
#   +--< $(photon-main)
#   |    +--< driver/built-in.o mm/built-in.o + more
#   |
#   +-< kallsyms.o (see description in CONFIG_KALLSYMS section)
#
# photon version (uname -v) cannot be updated during normal
# descending-into-subdirs phase since we do not yet know if we need to
# update photon.
# Therefore this step is delayed until just before final link of photon -
# except in the kallsyms case where it is done just before adding the
# symbols to the kernel.
#
# System.map is generated to document addresses of all kernel symbols

photon-init := $(head-y) $(init-y)
photon-main := $(core-y) $(libs-y) $(apps-y)
photon-all  := $(photon-init) $(photon-main)
photon-lds  := arch/$(ARCH)/kernel/photon.lds
export KBUILD_photon_OBJS := $(photon-all)

# Rule to link photon - also used during CONFIG_KALLSYMS
# May be overridden by arch/$(ARCH)/Makefile
quiet_cmd_photon__ ?= LD      $@
      cmd_photon__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_photon) -o $@ \
      -T $(photon-lds) $(photon-init)                          \
      --start-group $(photon-main) --end-group                  \
      $(filter-out $(photon-lds) $(photon-init) $(photon-main) photon.o FORCE ,$^)

# 生成photon版本号
quiet_cmd_photon_version = GEN     .version
      cmd_photon_version = set -e;                     \
	if [ ! -r .version ]; then			\
	  rm -f .version;				\
	  echo 1 >.version;				\
	else						\
	  mv .version .old_version;			\
	  expr 0$$(cat .old_version) + 1 >.version;	\
	fi;						\
	$(MAKE) $(build)=init

# 生成System.map
quiet_cmd_sysmap = SYSMAP
      cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap

# Link of photon
# If CONFIG_KALLSYMS is set .version is already updated
# Generate System.map and verify that the content is consistent
# Use + in front of the photon_version rule to silent warning with make -j2
# First command is ':' to allow us to use + in front of the rule
define rule_photon__
	:
	$(if $(CONFIG_KALLSYMS),,+$(call cmd,photon_version))

	$(call cmd,photon__)
	$(Q)echo 'cmd_$@ := $(cmd_photon__)' > $(@D)/.$(@F).cmd

	$(Q)$(if $($(quiet)cmd_sysmap),                                      \
	  echo '  $($(quiet)cmd_sysmap)  System.map' &&)                     \
	$(cmd_sysmap) $@ System.map;                                         \
	if [ $$? -ne 0 ]; then                                               \
		rm -f $@;                                                    \
		/bin/false;                                                  \
	fi;
	$(verify_kallsyms)
endef


ifdef CONFIG_KALLSYMS
# Generate section listing all symbols and add it into photon $(kallsyms.o)
# It's a three stage process:
# o .tmp_photon1 has all symbols and sections, but __kallsyms is
#   empty
#   Running kallsyms on that gives us .tmp_kallsyms1.o with
#   the right size - photon version (uname -v) is updated during this step
# o .tmp_photon2 now has a __kallsyms section of the right size,
#   but due to the added section, some addresses have shifted.
#   From here, we generate a correct .tmp_kallsyms2.o
# o The correct .tmp_kallsyms2.o is linked into the final photon.
# o Verify that the System.map from photon matches the map from
#   .tmp_photon2, just in case we did not generate kallsyms correctly.
# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using
#   .tmp_photon3 and .tmp_kallsyms3.o.  This is only meant as a
#   temporary bypass to allow the kernel to be built while the
#   maintainers work out what went wrong with kallsyms.

ifdef CONFIG_KALLSYMS_EXTRA_PASS
last_kallsyms := 3
else
last_kallsyms := 2
endif

kallsyms.o := .tmp_kallsyms$(last_kallsyms).o

define verify_kallsyms
	$(Q)$(if $($(quiet)cmd_sysmap),                                      \
	  echo '  $($(quiet)cmd_sysmap)  .tmp_System.map' &&)                \
	  $(cmd_sysmap) .tmp_photon$(last_kallsyms) .tmp_System.map
	$(Q)cmp -s System.map .tmp_System.map ||                             \
		(echo Inconsistent kallsyms data;                            \
		 echo Try setting CONFIG_KALLSYMS_EXTRA_PASS;                \
		 rm .tmp_kallsyms* ; /bin/true )
endef

# Update photon version before link
# Use + in front of this rule to silent warning about make -j1
# First command is ':' to allow us to use + in front of this rule
cmd_ksym_ld = $(cmd_photon__)
define rule_ksym_ld
	:
	+$(call cmd,photon_version)
	$(call cmd,photon__)
	$(Q)echo 'cmd_$@ := $(cmd_photon__)' > $(@D)/.$(@F).cmd
endef

# Generate .S file with all kernel symbols
quiet_cmd_kallsyms = KSYM    $@
      cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
                     $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@

.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
	$(call if_changed_dep,as_o_S)

.tmp_kallsyms%.S: .tmp_photon% $(KALLSYMS)
	$(call cmd,kallsyms)

# .tmp_photon1 must be complete except kallsyms, so update photon version
.tmp_photon1: $(photon-lds) $(photon-all) FORCE
	$(call if_changed_rule,ksym_ld)

.tmp_photon2: $(photon-lds) $(photon-all) .tmp_kallsyms1.o FORCE
	$(call if_changed,photon__)

.tmp_photon3: $(photon-lds) $(photon-all) .tmp_kallsyms2.o FORCE
	$(call if_changed,photon__)

# Needs to visit scripts/ before $(KALLSYMS) can be used.
$(KALLSYMS): scripts ;

# Generate some data for debugging strange kallsyms problems
debug_kallsyms: .tmp_map$(last_kallsyms)

.tmp_map%: .tmp_photon% FORCE
	($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@

.tmp_map3: .tmp_map2

.tmp_map2: .tmp_map1

endif # ifdef CONFIG_KALLSYMS

# Do modpost on a prelinked photon. The finally linked photon has
# relevant sections renamed as per the linker script.
quiet_cmd_photon-modpost = LD      $@
      cmd_photon-modpost = $(LD) $(LDFLAGS) -r -o $@                          \
	 $(photon-init) --start-group $(photon-main) --end-group             \
	 $(filter-out $(photon-init) $(photon-main) FORCE ,$^)
define rule_photon-modpost
	:
	+$(call cmd,photon-modpost)
endef

# photon image - including updated kernel symbols
photon: $(photon-lds) $(photon-init) $(photon-main) photon.o $(kallsyms.o) FORCE
ifdef CONFIG_HEADERS_CHECK
	$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
endif
	$(call photon-modpost)
	$(call if_changed_rule,photon__)
	$(Q)rm -f .old_version


# build photon.o first to catch section mismatch errors early
ifdef CONFIG_KALLSYMS
.tmp_photon1: photon.o
endif

modpost-init := $(filter-out init/built-in.o, $(photon-init))
photon.o: $(modpost-init) $(photon-main) FORCE
	$(call if_changed_rule,photon-modpost)

# The actual objects are generated when descending,
# make sure no implicit rule kicks in
$(sort $(photon-init) $(photon-main)) $(photon-lds): $(photon-dirs) ;

# Handle descending into subdirectories listed in $(photon-dirs)
# Preset locale variables to speed up the build process. Limit locale
# tweaks to this spot to avoid wrong language settings when running
# make menuconfig etc.
# Error messages still appears in the original language

PHONY += $(photon-dirs)
$(photon-dirs): prepare scripts
	$(Q)$(MAKE) $(build)=$@

# Store (new) KERNELRELASE string in include/config/kernel.release
include/config/kernel.release: include/config/auto.conf FORCE
	$(Q)rm -f $@
	$(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@


# Things we need to do before we recursively start building the kernel
# or the modules are listed in "prepare".
# A multi level approach is used. prepareN is processed before prepareN-1.
# archprepare is used in arch Makefiles and when processed asm symlink,
# version.h and scripts_basic is processed / created.

# Listed in dependency order
PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3

# prepare3 is used to check if we are building in a separate output directory,
# and if so do:
# 1) Check that make has not been executed in the kernel src $(srctree)
prepare3: include/config/kernel.release
ifneq ($(KBUILD_SRC),)
	@$(kecho) '  Using $(srctree) as source for kernel'
	$(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
		echo "  $(srctree) is not clean, please run 'make mrproper'";\
		echo "  in the '$(srctree)' directory.";\
		/bin/false; \
	fi;
endif

# prepare2 creates a makefile if using a separate output directory
prepare2: prepare3

prepare1: prepare2 include/generated/utsrelease.h \
                   include/config/auto.conf

archprepare: prepare1 scripts_basic

prepare0: archprepare FORCE
	$(Q)$(MAKE) $(build)=.
	$(Q)$(MAKE) $(build)=. missing-syscalls

# All the preparing..
prepare: prepare0

# Generate some files
# ---------------------------------------------------------------------------

# KERNELRELEASE can change from a few different places, meaning version.h
# needs to be updated, so this check is forced on all builds

uts_len := 64
define filechk_utsrelease.h
	if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
	  echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2;    \
	  exit 1;                                                         \
	fi;                                                               \
	(echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";)
endef

define filechk_version.h
	(echo \#define PHOTON_VERSION_CODE $(shell                             \
	expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + $(SUBLEVEL));     \
	echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
endef

include/generated/utsrelease.h: include/config/kernel.release FORCE
	$(call filechk,utsrelease.h)

PHONY += headerdep
headerdep:
	$(Q)find include/ -name '*.h' | xargs --max-args 1 scripts/headerdep.pl

# ---------------------------------------------------------------------------

PHONY += depend dep
depend dep:
	@echo '*** Warning: make $@ is unnecessary now.'

# ---------------------------------------------------------------------------
# Firmware install
INSTALL_FW_PATH=$(INSTALL_MOD_PATH)/lib/firmware
export INSTALL_FW_PATH

PHONY += firmware_install
firmware_install: FORCE
	@mkdir -p $(objtree)/firmware
	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install

# ---------------------------------------------------------------------------
# Kernel headers

#Default location for installed headers
export INSTALL_HDR_PATH = $(objtree)/usr

hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj

# If we do an all arch process set dst to asm-$(ARCH)
hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(ARCH), dst=include/asm)

PHONY += __headers
__headers: scripts_basic FORCE
	$(Q)$(MAKE) $(build)=scripts scripts/unifdef

PHONY += headers_install_all
headers_install_all:
	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh install

PHONY += headers_install
headers_install: __headers
	$(if $(wildcard $(srctree)/arch/$(ARCH)/include/asm/Kbuild),, \
	$(error Headers not exportable for the $(ARCH) architecture))
	$(Q)$(MAKE) $(hdr-inst)=include
	$(Q)$(MAKE) $(hdr-inst)=arch/$(ARCH)/include/asm $(hdr-dst)

PHONY += headers_check_all
headers_check_all: headers_install_all
	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh check

PHONY += headers_check
headers_check: headers_install
	$(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1
	$(Q)$(MAKE) $(hdr-inst)=arch/$(ARCH)/include/asm $(hdr-dst) HDRCHECK=1

#
# 编译时要清除的文件
#
CLEAN_FILES +=	photon System.map \
                .tmp_kallsyms* .tmp_version .tmp_photon* .tmp_System.map

# Directories & files removed with 'make mrproper'
MRPROPER_DIRS  += include/config include/generated
MRPROPER_FILES += .config .config.old .version .old_version             \
		  Module.symvers tags TAGS cscope*

# clean - Delete most, but leave enough to build external modules
#
clean: rm-dirs  := $(CLEAN_DIRS)
clean: rm-files := $(CLEAN_FILES)
clean-dirs      := $(addprefix _clean_,$(srctree) $(photon-alldirs))

PHONY += $(clean-dirs) clean archclean
$(clean-dirs):
	$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)

clean: archclean $(clean-dirs)
	$(call cmd,rmdirs)
	$(call cmd,rmfiles)
	@find . $(RCS_FIND_IGNORE) \
		\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
		-o -name '*.symtypes' -o -name 'modules.order' \
		-o -name modules.builtin -o -name '.tmp_*.o.*' \
		-o -name '*.gcno' \) -type f -print | xargs rm -f

# mrproper - Delete all generated files, including .config
#
mrproper: rm-dirs  := $(wildcard $(MRPROPER_DIRS))
mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
mrproper-dirs      := $(addprefix _mrproper_,)

PHONY += $(mrproper-dirs) mrproper archmrproper
$(mrproper-dirs):
	$(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)

mrproper: clean archmrproper $(mrproper-dirs)
	$(call cmd,rmdirs)
	$(call cmd,rmfiles)

# distclean
#
PHONY += distclean

distclean: mrproper
	@find $(srctree) $(RCS_FIND_IGNORE) \
		\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
		-o -name '.*.rej' \
		-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
		-type f -print | xargs rm -f

# Packaging of the kernel to various formats
# ---------------------------------------------------------------------------
# rpm target kept for backward compatibility
package-dir	:= $(srctree)/scripts/package

%src-pkg: FORCE
	$(Q)$(MAKE) $(build)=$(package-dir) $@
%pkg: include/config/kernel.release FORCE
	$(Q)$(MAKE) $(build)=$(package-dir) $@
rpm: include/config/kernel.release FORCE
	$(Q)$(MAKE) $(build)=$(package-dir) $@

# Brief documentation of the typical targets used
# ---------------------------------------------------------------------------

# Documentation targets
# ---------------------------------------------------------------------------
%docs: scripts_basic FORCE
	$(Q)$(MAKE) $(build)=$@


# Generate tags for editors
# ---------------------------------------------------------------------------
quiet_cmd_tags = GEN     $@
      cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@

tags TAGS cscope: FORCE
	$(call cmd,tags)

# Scripts to check various things for consistency
# ---------------------------------------------------------------------------

#通过脚本检查头文件，确定需要重新编译哪些文件
includecheck:
	find * $(RCS_FIND_IGNORE) \
		-name '*.[hcS]' -type f -print | sort \
		| xargs $(PERL) -w $(srctree)/scripts/checkincludes.pl

versioncheck:
	find * $(RCS_FIND_IGNORE) \
		-name '*.[hcS]' -type f -print | sort \
		| xargs $(PERL) -w $(srctree)/scripts/checkversion.pl

coccicheck:
	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@

namespacecheck:
	$(PERL) $(srctree)/scripts/namespace.pl

export_report:
	$(PERL) $(srctree)/scripts/export_report.pl

endif #ifeq ($(config-targets),1)
endif #ifeq ($(mixed-targets),1)

PHONY +=  kernelrelease kernelversion

kernelrelease:
	@echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))"

kernelversion:
	@echo $(KERNELVERSION)

# Single targets
# ---------------------------------------------------------------------------
# Single targets are compatible with:
# - build with mixed source and output
# - build with separate output dir 'make O=...'
# - external modules
#
#  target-dir => where to store outputfile
#  build-dir  => directory in kernel source tree to use

ifeq ($(KBUILD_EXTMOD),)
        build-dir  = $(patsubst %/,%,$(dir $@))
        target-dir = $(dir $@)
else
        zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
        build-dir  = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
        target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@))
endif

%.s: %.c prepare scripts FORCE
	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.i: %.c prepare scripts FORCE
	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.o: %.c prepare scripts FORCE
	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.lst: %.c prepare scripts FORCE
	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.s: %.S prepare scripts FORCE
	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.o: %.S prepare scripts FORCE
	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.symtypes: %.c prepare scripts FORCE
	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)

# Modules
/: prepare scripts FORCE
	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
	$(build)=$(build-dir)
%/: prepare scripts FORCE
	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
	$(build)=$(build-dir)
%.ko: prepare scripts FORCE
	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1)   \
	$(build)=$(build-dir) $(@:.ko=.o)
	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost

# FIXME Should go into a make.lib or something
# ===========================================================================

quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN   $(wildcard $(rm-dirs)))
      cmd_rmdirs = rm -rf $(rm-dirs)

quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files)))
      cmd_rmfiles = rm -f $(rm-files)

a_flags = -Wp,-MD,$(depfile) $(KBUILD_AFLAGS) $(AFLAGS_KERNEL) \
	  $(KBUILD_AFLAGS_KERNEL)                              \
	  $(NOSTDINC_FLAGS) $(PHOTONINCLUDE) $(KBUILD_CPPFLAGS) \
	  $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)

quiet_cmd_as_o_S = AS      $@
cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<

# read all saved command lines

targets := $(wildcard $(sort $(targets)))
cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))

ifneq ($(cmd_files),)
  $(cmd_files): ;	# Do not try to update included dependency files
  include $(cmd_files)
endif

# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
# Usage:
# $(Q)$(MAKE) $(clean)=dir
clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj


PHONY += FORCE
FORCE:

# Declare the contents of the .PHONY variable as phony.  We keep that
# information in a variable so we can use it in if_changed and friends.
.PHONY: $(PHONY)
